package com.linsen.erp.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.linsen.core.common.context.TokenContextHolder;
import com.linsen.core.common.enums.DeleteType;
import com.linsen.core.common.enums.UseStatusType;
import com.linsen.core.common.enums.YnType;
import com.linsen.core.common.exception.BaseException;
import com.linsen.core.common.model.User;
import com.linsen.core.common.util.ConvertUtil;
import com.linsen.core.common.util.RandomUtil;
import com.linsen.core.common.util.ShaUtil;
import com.linsen.core.redis.util.RedisSecurityUtil;
import com.linsen.erp.admin.entity.RoleEntity;
import com.linsen.erp.admin.entity.UserEntity;
import com.linsen.erp.admin.mapper.UserMapper;
import com.linsen.erp.admin.provider.dto.EmployeeDTO;
import com.linsen.erp.admin.provider.dto.UserDTO;
import com.linsen.erp.admin.provider.qo.UserListQo;
import com.linsen.erp.admin.provider.qo.UserQo;
import com.linsen.erp.admin.provider.vo.RoleVO;
import com.linsen.erp.admin.provider.vo.UserVO;
import com.linsen.erp.admin.service.IDeptService;
import com.linsen.erp.admin.service.IRoleService;
import com.linsen.erp.admin.service.IUserRoleService;
import com.linsen.erp.admin.service.IUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author zhaoyong
 * @since 2023-07-24
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements IUserService {

    private final RedisSecurityUtil redisSecurityUtil;
    private final IUserRoleService iUserRoleService;
    private IDeptService iDeptService;
    @Autowired
    public void setiDeptService(IDeptService iDeptService) {
        this.iDeptService = iDeptService;
    }
    private IRoleService iRoleService;
    @Autowired
    public void setiRoleService(IRoleService iRoleService) {
        this.iRoleService = iRoleService;
    }

    @Override
    public UserVO current() {
        User user = this.redisSecurityUtil.getUser(TokenContextHolder.getToken());
        String userid = user.getUserid();

        return get(userid);
    }

    @Transactional
    @Override
    public void updateCurrent(UserDTO userDTO) {
        User user = this.redisSecurityUtil.getUser(TokenContextHolder.getToken());
        String userid = user.getUserid();

        userDTO.setId(userid);

        updateUser(userDTO);
    }

    /** 封装分页列表查询的wrapper对象 */
    private Wrapper<UserEntity> getWrapper(UserQo userQo){
        String username = userQo.getUsername();
        String name = userQo.getName();
        String tel = userQo.getTel();
        List<String> deptIdList = userQo.getDeptIdList();
        Integer status = userQo.getStatus();
        Integer isAdmin = userQo.getIsAdmin();

        return new LambdaQueryWrapper<UserEntity>()
                .like(ObjectUtil.isNotEmpty(username),UserEntity::getUsername,username)
                .like(ObjectUtil.isNotEmpty(name),UserEntity::getName,name)
                .like(ObjectUtil.isNotEmpty(tel),UserEntity::getTel,tel)
                // .eq(ObjectUtil.isNotEmpty(deptIdList)&&deptIdList.size()==1,UserEntity::getDeptId,deptIdList.get(0))
                .in(ObjectUtil.isNotEmpty(deptIdList),UserEntity::getDeptId,deptIdList)
                .eq(ObjectUtil.isNotNull(status),UserEntity::getStatus,status)
                .eq(ObjectUtil.isNotNull(isAdmin),UserEntity::getIsAdmin,isAdmin)
                .eq(UserEntity::getIsDeleted, DeleteType.NORMAL.getValue())
                .orderByDesc(UserEntity::getCreateTime);
    }

    @Override
    public Page<UserVO> page(UserQo qo) {
        //处理部门id过滤条件
        String deptId = qo.getDeptId();
        Integer isFetch = qo.getIsFetch();
        if (ObjectUtil.isNotEmpty(deptId)){
            List<String> deptIdList = new ArrayList<>();
            if (ObjectUtil.equal(isFetch,YnType.YES.getValue())){
                deptIdList.addAll(iDeptService.getSubDeptidList(deptId));
            }else{
                deptIdList.add(deptId);
            }
            qo.setDeptIdList(deptIdList);
        }

        Page<UserEntity> page = this.page(new Page<>(qo.getCurrent(), qo.getSize()), getWrapper(qo));

        Page<UserVO> userVOPage = new Page<>(qo.getCurrent(), qo.getSize());
        userVOPage.setTotal(page.getTotal());

        //获取全部角色列表信息
        Map<String, RoleVO> roleVOMap = ConvertUtil.convert(
                iRoleService.list(
                        new LambdaQueryWrapper<RoleEntity>()
                                .eq(RoleEntity::getIsDeleted, DeleteType.NORMAL.getValue())
                ),RoleVO.class).stream().collect(Collectors.toMap(RoleVO::getId, Function.identity(), (key1, key2) -> key2));

        List<UserVO> userVOList = new ArrayList<>();
        page.getRecords().forEach(userEntity -> {
            UserVO userVO = ConvertUtil.convert(userEntity, UserVO.class);

            userVO.setDeptVO(iDeptService.get(userVO.getDeptId()));

            List<String> roleIdList = iUserRoleService.getRoleIdByUserId(userVO.getId());
            List<RoleVO> roleVOList = roleIdList.stream().map(roleVOMap::get).filter(ObjectUtil::isNotNull).collect(Collectors.toList());

            userVO.setRoleIdList(roleIdList);
            userVO.setRoleVOList(roleVOList);

            userVOList.add(userVO);
        });
        userVOPage.setRecords(userVOList);

        return userVOPage;
    }

    @Override
    public List<UserVO> list(UserListQo userListQo) {
        String keyword = userListQo.getKeyword();

        return ConvertUtil.convert(this.list(
                new LambdaQueryWrapper<UserEntity>()
                        .and(ObjectUtil.isNotEmpty(keyword),wrapper ->
                                wrapper.like(UserEntity::getUsername,keyword)
                                        .or()
                                        .like(UserEntity::getName,keyword)
                                        .or()
                                        .like(UserEntity::getTel,keyword))
                        .eq(UserEntity::getIsDeleted,DeleteType.NORMAL.getValue())
        ),UserVO.class);
    }

    @Override
    public UserVO get(String id) {
        UserEntity userEntity = this.getById(id);
        UserVO userVO = ConvertUtil.convert(userEntity, UserVO.class);

        userVO.setDeptVO(iDeptService.get(userVO.getDeptId()));

        List<String> roleIdList = iUserRoleService.getRoleIdByUserId(id);
        if (ObjectUtil.isNotEmpty(roleIdList)){
            List<RoleEntity> roleEntityList = iRoleService.list(
                    new LambdaQueryWrapper<RoleEntity>()
                            .in(RoleEntity::getId, roleIdList)
                            .eq(RoleEntity::getIsDeleted, DeleteType.NORMAL.getValue())
            );
            userVO.setRoleVOList(ConvertUtil.convert(roleEntityList,RoleVO.class));
        }
        userVO.setRoleIdList(roleIdList);

        return userVO;
    }

    @Transactional
    @Override
    public void saveUser(UserDTO userDTO) {
        String username = userDTO.getUsername();
        String password = userDTO.getPassword();

        //账户username必须唯一
        List<UserEntity> userEntityList = this.list(
                new LambdaQueryWrapper<UserEntity>()
                        .eq(UserEntity::getUsername, username)
                        .eq(UserEntity::getIsDeleted, DeleteType.NORMAL.getValue())
        );
        if (ObjectUtil.isNotEmpty(userEntityList)){
            throw new BaseException("账户username必须唯一");
        }

        UserEntity userEntity = ConvertUtil.convert(userDTO, UserEntity.class);
        userEntity.setIsSuper(YnType.NO.getValue());
        userEntity.setPassword(ShaUtil.encrypt(ObjectUtil.isNotEmpty(password)?password:"123456"));

        this.save(userEntity);

        if (ObjectUtil.equal(userEntity.getIsAdmin(), YnType.NO.getValue())){
            iUserRoleService.set(userEntity.getId(),userDTO.getRoleIdList());
        }
    }

    @Transactional
    @Override
    public void updateUser(UserDTO userDTO) {
        String id = userDTO.getId();
        String username = userDTO.getUsername();
        String password = userDTO.getPassword();

        //账户username必须唯一
        List<UserEntity> userEntityList = this.list(
                new LambdaQueryWrapper<UserEntity>()
                        .ne(UserEntity::getId,id)
                        .eq(UserEntity::getUsername, username)
                        .eq(UserEntity::getIsDeleted, DeleteType.NORMAL.getValue())
        );
        if (ObjectUtil.isNotEmpty(userEntityList)){
            throw new BaseException("账户username必须唯一");
        }

        UserEntity userEntity = this.getById(id);
        if(ObjectUtil.equal(userEntity.getIsSuper(),YnType.YES.getValue())){
            //默认超级管理员账号，某些信息禁止变更
            userDTO.setStatus(UseStatusType.NORMAL.getValue());
            userDTO.setIsAdmin(YnType.YES.getValue());
        }

        if (ObjectUtil.equal(userDTO.getIsAdmin(),YnType.YES.getValue())){
            iUserRoleService.set(id,null);
        }else{
            iUserRoleService.set(id,userDTO.getRoleIdList());
        }

        BeanUtil.copyProperties(userDTO, userEntity);
        if (ObjectUtil.isNotEmpty(password)){
            userEntity.setPassword(ShaUtil.encrypt(password));
        }

        this.updateById(userEntity);
    }

    @Transactional
    @Override
    public void useStatus(String id) {
        UserEntity userEntity = this.getById(id);
        if(ObjectUtil.equal(userEntity.getIsSuper(),YnType.YES.getValue())){
            //默认超级管理员账号，某些信息禁止变更
            throw new BaseException("默认超级管理员不允许账户冻结");
        }

        userEntity.setStatus(userEntity.getStatus() ^ 1);
        this.updateById(userEntity);
    }

    @Transactional
    @Override
    public void delete(String id) {
        UserEntity userEntity = this.getById(id);
        if(ObjectUtil.equal(userEntity.getIsSuper(),YnType.YES.getValue())){
            //默认超级管理员账号，某些信息禁止变更
            throw new BaseException("默认超级管理员不允许账户删除");
        }

        this.update(
                new UpdateWrapper<UserEntity>().lambda()
                        .set(UserEntity::getIsDeleted,DeleteType.DELETED.getValue())
                        .eq(UserEntity::getId,id)
        );
    }

    @Transactional
    @Override
    public void resetPassword(String id) {
        // SHA256算法（默认密码为123456）
        String password = ShaUtil.encrypt("123456");

        this.update(
                new UpdateWrapper<UserEntity>().lambda()
                        .set(UserEntity::getPassword,password)
                        .eq(UserEntity::getId,id)
        );
    }

    @Transactional
    @Override
    public UserEntity createByEmployee(EmployeeDTO employeeDTO) {
        // SHA256算法（默认密码为123456）
        String password = ShaUtil.encrypt("123456");

        UserEntity userEntity = new UserEntity();
        userEntity.setUsername(RandomUtil.randomNumberLetter(8));
        userEntity.setPassword(password);
        userEntity.setName(employeeDTO.getName());
        userEntity.setGender(employeeDTO.getGender());
        userEntity.setAge(null);//理论上可以通过身份证号或出生日期推断出来
        userEntity.setEmail(null);
        userEntity.setTel(employeeDTO.getTel());
        userEntity.setDeptId(employeeDTO.getDeptid());
        userEntity.setStatus(UseStatusType.NORMAL.getValue());
        userEntity.setIsSuper(YnType.NO.getValue());
        userEntity.setIsAdmin(YnType.NO.getValue());
        this.save(userEntity);

        return userEntity;
    }
}
